/*###################################################################*
#
# MP (Mitchell Pell) Base - CrossPlatform Base Utilities.
# Copyright (C) 2014  Mitchell Pell
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
####################################################################*/

#ifndef BASE_THREADED_H
#define BASE_THREADED_H

#include <boost/thread.hpp>

namespace mp_base{
	namespace interfaces{

		typedef boost::shared_ptr<boost::thread> shpThread;

		class Threaded
		{
		public:
			Threaded(){ m_stopRequested = false; m_thread.reset(); }
			virtual ~Threaded()
			{
				if (m_thread.get() != NULL)
				{
					m_stopRequested = true;

					m_thread->join();
					m_thread.reset();
				}
			}

			bool StartThread()
			{
				m_stopRequested = false;
				try
				{
					m_thread.reset(
						new boost::thread(boost::bind(
						&Threaded::ThreadProc, this)));
				}
				catch (boost::exception const&  ex)
				{
					//Handle Error

					//Clear thread
					m_thread.reset();
					//return failure
					return false;
				}
				//return success
				return true;

			}

			bool StopThread(bool wait = false)
			{
				long count = m_thread.use_count();
				if (count > 0)
				{
					m_stopRequested = true;
					if (wait){
						m_thread->join();
					}
					m_thread.reset();
					return true;
				}
				else
					return false;
			}

			/*! Operating thread */
			void ThreadProc()
			{
				m_stopRequested = false;
				ThreadInitialization();
				while (!m_stopRequested)
				{
					ThreadUpdate();
				}
				ThreadShutdown();
			}

			bool IsStopRequested(){ return m_stopRequested; }

		protected:

			virtual void ThreadInitialization() = 0;
			virtual void ThreadUpdate() = 0;
			virtual void ThreadShutdown() = 0;

			volatile bool	m_stopRequested;
			shpThread		m_thread;
		};
	}
}
#endif